﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Silvermoon.UI;
using Silvermoon.Windows.Styles;
using Silvermoon.Shapes;
using Silvermoon.Windows;
using Silvermoon.Images;
using Silvermoon.Classes;

namespace Silvermoon.Controls
{
    public enum DatePickerMode
    {
        /// <summary>
        /// selects date, month and year.
        /// </summary>
        Date,

        /// <summary>
        /// selects month and year.
        /// </summary>
        MonthYear
    }

    public class DatePickerDialog : Window
    {

        private DatePickerMode mode = DatePickerMode.Date;
        private Picker dayPicker;
        private Picker monthPicker;
        private Picker yearPicker;
        private AnimationGrid grid;
        private DatePickerModel model;
        private ToolbarButton saveButton;

        public DatePickerDialog()
            : base()
        {
            InitializePage();
        }

        public DatePickerMode Mode
        {
            get { return mode; }
            set
            {
                if (mode != value)
                {
                    mode = value;
                    ArrangeGrid();
                }
            }
        }

        public bool IsSaveEnabled
        {
            get { return saveButton.Enabled; }
            set { saveButton.Enabled = value; }
        }

        public DateTime Date
        {
            get { return GetDateFromPicker(); }
            set
            {
                SetPickerDate(value);
            }
        }

        private void SetPickerDate(DateTime value)
        {
            if (value.IsEmpty()) value = DateTime.Now;
            SetDays(value.Year, value.Month, value.Day);
        }

        private DateTime GetDateFromPicker()
        {
            int year = model.GetYearFromIndex(yearPicker.SelectedItemIndex);
            int month = model.GetMonthFromIndex(monthPicker.SelectedItemIndex);
            int day = mode == DatePickerMode.Date ? model.GetDayFromIndex(dayPicker.SelectedItemIndex) : 1;
            return new DateTime(year, month, day);
        }

        protected override void Dispose(bool dispose)
        {
            base.Dispose(dispose);
        }

        private void InitializePage()
        {
            SetTransition(300, TransitionMask.Fade | TransitionMask.Zoom, TransitionMask.Fade | TransitionMask.Explode);
            Title = "CHOOSE DATE";

            const PickerMode pm = PickerMode.Fade | PickerMode.AutoHide;
            Styles.SetClass<Picker>(new PickerStyle
            {
                ItemHeight = 140,
                Lense = Shape.Empty,
                IsCyclic = true,
                Mode = pm,
                Margin = Margin.Zero,
                TextColor = PhoneColors.White
            });

            model = new DatePickerModel();

            dayPicker = new Picker();
            monthPicker = new Picker { Margin = new Margin(0, 0, 0, 0) };
            yearPicker = new Picker();


            grid = new AnimationGrid { Margin = Margin.Zero };

            grid.AddControl(model.GetDayIndex(), dayPicker);
            grid.AddControl(model.GetMonthIndex(), monthPicker);
            grid.AddControl(model.GetYearIndex(), yearPicker);
            Controls.Add(grid);

            BindModel();
            Date = DateTime.Now.Date;
            ArrangeGrid();

            Toolbar tb = new Toolbar();

            saveButton = tb.AddButton(SysImages.Ok);
            tb.AddButton(SysImages.RecycleBin).Tap += new EventHandler<TapEventArgs>(OnClear);
            tb.AddButton(SysImages.Cancel).Tap += (s, e) => GoBack();
            saveButton.Tap += new EventHandler<TapEventArgs>(OnOk);
            Toolbar = tb;
        }

        void OnClear(object sender, TapEventArgs e)
        {
            OnSelected(DateUtil.EmptyDate);
        }

        void OnOk(object sender, TapEventArgs e)
        {
            OnSelected(Date);
        }

        protected virtual void OnSelected(DateTime date)
        {
            if (Selected != null) Selected(this, new DateEventArgs(date));
            GoBack();
        }

        protected override void OnShown()
        {
            monthPicker.SelectedItemChanged += new EventHandler(OnSelectedItemChanged);
            yearPicker.SelectedItemChanged += new EventHandler(OnSelectedItemChanged);
            dayPicker.SelectedItemChanged += (s, e) => IsSaveEnabled = true;
            base.OnShown();
        }

        private void ArrangeGrid()
        {
            switch (Mode)
            {
                case DatePickerMode.Date: ArrangeDate(); break;
                case DatePickerMode.MonthYear: ArrangeMonthYear(); break;
                default: throw new NotSupportedException();
            }
        }

        private void ArrangeDate()
        {
            GridDefinition def = new GridDefinition();
            def.Columns.AddRange(2f, 2f, 2f);
            def.Rows.AddRange(1f);
            def.CreateAutoCells();

            grid.Controls.Clear();
            grid.Definition = def;
            grid.AddControl(model.GetDayIndex(), dayPicker);
            grid.AddControl(model.GetMonthIndex(), monthPicker);
            grid.AddControl(model.GetYearIndex(), yearPicker);
        }

        private void ArrangeMonthYear()
        {
            GridDefinition def = new GridDefinition();
            def.Columns.AddRange(1f, 2f, 2f, 1f);
            def.Rows.AddRange(1f);
            def.CreateAutoCells();

            grid.Controls.Clear();
            grid.Definition = def;
            grid.AddControl(1, monthPicker);
            grid.AddControl(2, yearPicker);
        }

        void OnSelectedItemChanged(object sender, EventArgs e)
        {
            if (yearPicker.SelectedItemIndex >= 0 && monthPicker.SelectedItemIndex >= 0 && dayPicker.SelectedItemIndex >= 0)
            {
                int year = model.GetYearFromIndex(yearPicker.SelectedItemIndex);
                int month = model.GetMonthFromIndex(monthPicker.SelectedItemIndex);
                int day = model.GetDayFromIndex(dayPicker.SelectedItemIndex);
                SetDays(year, month, day);
            }
            IsSaveEnabled = true;
        }

        private void BindModel()
        {
            dayPicker.GetVirtualItem += OnGetPickerItem;
            monthPicker.GetVirtualItem += OnGetPickerItem;
            yearPicker.GetVirtualItem += OnGetPickerItem;

            monthPicker.ItemsSource = model.Months;
            yearPicker.ItemsSource = model.Years;

        }

        private void SetDays(int year, int month, int day)
        {
            monthPicker.SelectedItemIndex = model.GetIndexFromMonth(month);
            yearPicker.SelectedItemIndex = model.GetIndexFromYear(year);
            if (mode == DatePickerMode.Date)
            {
                dayPicker.ItemsSource = model.GetDays(month, year);
                dayPicker.SelectedItemIndex = model.GetIndexFromDay(day);
            }
        }

        void OnGetPickerItem(object sender, PickerItemEventArgs e)
        {
            var item = DatePickerItem.GetItem();
            item.DataValue = e.Value;
            e.Container = item;
        }

        protected override void OnBack(HandledEventArgs e)
        {
            base.OnBack(e);
            Hide();
        }

        protected override void OnHidden()
        {
            base.OnHidden();
            Dispose();
        }


        public event EventHandler<DateEventArgs> Selected;
    }
}
